home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / program / tcpdumpb.zip / tcpdump.c < prev    next >
C/C++ Source or Header  |  1997-04-13  |  14KB  |  430 lines

  1. /*
  2.  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
  3.  *      The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that: (1) source code distributions
  7.  * retain the above copyright notice and this paragraph in its entirety, (2)
  8.  * distributions including binary code include the above copyright notice and
  9.  * this paragraph in its entirety in the documentation or other materials
  10.  * provided with the distribution, and (3) all advertising materials mentioning
  11.  * features or use of this software display the following acknowledgement:
  12.  * ``This product includes software developed by the University of California,
  13.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14.  * the University nor the names of its contributors may be used to endorse
  15.  * or promote products derived from this software without specific prior
  16.  * written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  */
  21.  
  22. #ifndef lint
  23. char copyright[] =
  24.     "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996\n\
  25. The Regents of the University of California.  All rights reserved.\n";
  26. static  char rcsid[] =
  27.     "@(#)$Header: tcpdump.c,v 1.114 96/07/17 00:12:40 leres Exp $ (LBL)";
  28. #endif
  29.  
  30. /*
  31.  * tcpdump - monitor tcp/ip traffic on an ethernet.
  32.  *
  33.  * First written in 1987 by Van Jacobson, Lawrence Berkeley Laboratory.
  34.  * Mercilessly hacked and occasionally improved since then via the
  35.  * combined efforts of Van, Steve McCanne and Craig Leres of LBL.
  36.  */
  37.  
  38. #include <sys/types.h>
  39. #include <sys/time.h>
  40.  
  41. #include <netinet/in.h>
  42.  
  43. #include <pcap.h>
  44. #include <signal.h>
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <string.h>
  48. #include <unistd.h>
  49.  
  50. #include "interface.h"
  51. #include "addrtoname.h"
  52. #include "machdep.h"
  53.  
  54. int fflag;                      /* don't translate "foreign" IP address */
  55. int nflag;                      /* leave addresses as numbers */
  56. int Nflag;                      /* remove domains from printed host names */
  57. int pflag;                      /* don't go promiscuous */
  58. int qflag;                      /* quick (shorter) output */
  59. int tflag = 1;                  /* print packet arrival time */
  60. int eflag;                      /* print ethernet header */
  61. int vflag;                      /* verbose */
  62. int xflag;                      /* print packet in hex */
  63. int Oflag = 1;                  /* run filter code optimizer */
  64. int Sflag;                      /* print raw TCP sequence numbers */
  65. int packettype;
  66.  
  67. int dflag;                      /* print filter code */
  68.  
  69. char *program_name;
  70.  
  71. int32_t thiszone;               /* seconds offset from gmt to local time */
  72.  
  73. /* Externs */
  74. extern void bpf_dump(struct bpf_program *, int);
  75.  
  76. /* Forwards */
  77. RETSIGTYPE cleanup(int);
  78. extern __dead void usage(void) __attribute__((volatile));
  79.  
  80. /* Length of saved portion of packet. */
  81. int snaplen = DEFAULT_SNAPLEN;
  82.  
  83. struct printer {
  84.         pcap_handler f;
  85.         int type;
  86. };
  87.  
  88. /* XXX needed if using old bpf.h */
  89. #ifndef DLT_ATM_RFC1483
  90. #define DLT_ATM_RFC1483 11
  91. #endif
  92.  
  93. static struct printer printers[] = {
  94.         { ether_if_print,       DLT_EN10MB },
  95.         { ether_if_print,       DLT_IEEE802 },
  96.         { sl_if_print,          DLT_SLIP },
  97.         { ppp_if_print,         DLT_PPP },
  98.         { fddi_if_print,        DLT_FDDI },
  99.         { null_if_print,        DLT_NULL },
  100.         { atm_if_print,         DLT_ATM_RFC1483 },
  101.         { NULL,                 0 },
  102. };
  103.  
  104. static pcap_handler
  105. lookup_printer(int type)
  106. {
  107.         struct printer *p;
  108.  
  109.         for (p = printers; p->f; ++p)
  110.                 if (type == p->type)
  111.                         return p->f;
  112.  
  113.         error("unknown data link type 0x%x", type);
  114.         /* NOTREACHED */
  115. }
  116.  
  117. static pcap_t *pd;
  118.  
  119. extern int optind;
  120. extern int opterr;
  121. extern char *optarg;
  122.  
  123. int
  124. main(int argc, char **argv)
  125. {
  126.         register int cnt, op, i;
  127.         bpf_u_int32 localnet, netmask;
  128.         register char *cp, *infile, *cmdbuf, *device, *RFileName, *WFileName;
  129.         pcap_handler printer;
  130.         struct bpf_program fcode;
  131.         u_char *pcap_userdata;
  132.         char ebuf[PCAP_ERRBUF_SIZE];
  133.  
  134.         cnt = -1;
  135.         device = NULL;
  136.         infile = NULL;
  137.         RFileName = NULL;
  138.         WFileName = NULL;
  139.         if ((cp = strrchr(argv[0], '/')) != NULL)
  140.                 program_name = cp + 1;
  141.         else
  142.                 program_name = argv[0];
  143.  
  144.         if (abort_on_misalignment(ebuf) < 0)
  145.                 error(ebuf);
  146.  
  147.         opterr = 0;
  148.         while ((op = getopt(argc, argv, "c:defF:i:lnNOpqr:s:StT:vw:xY")) != EOF)
  149.                 switch (op) {
  150.                 case 'c':
  151.                         cnt = atoi(optarg);
  152.                         if (cnt <= 0)
  153.                                 error("invalid packet count %s", optarg);
  154.                         break;
  155.  
  156.                 case 'd':
  157.                         ++dflag;
  158.                         break;
  159.  
  160.                 case 'e':
  161.                         ++eflag;
  162.                         break;
  163.  
  164.                 case 'f':
  165.                         ++fflag;
  166.                         break;
  167.  
  168.                 case 'F':
  169.                         infile = optarg;
  170.                         break;
  171.  
  172.                 case 'i':
  173.                         device = optarg;
  174.                         break;
  175.  
  176.                 case 'l':
  177. #ifdef HAVE_SETLINEBUF
  178.                         setlinebuf(stdout);
  179. #else
  180.                         setvbuf(stdout, NULL, _IOLBF, 0);
  181. #endif
  182.                         break;
  183.  
  184.                 case 'n':
  185.                         ++nflag;
  186.                         break;
  187.  
  188.                 case 'N':
  189.                         ++Nflag;
  190.                         break;
  191.  
  192.                 case 'O':
  193.                         Oflag = 0;
  194.                         break;
  195.  
  196.                 case 'p':
  197.                         ++pflag;
  198.                         break;
  199.  
  200.                 case 'q':
  201.                         ++qflag;
  202.                         break;
  203.  
  204.                 case 'r':
  205.                         RFileName = optarg;
  206.                         break;
  207.  
  208.                 case 's':
  209.                         snaplen = atoi(optarg);
  210.                         if (snaplen <= 0)
  211.                                 error("invalid snaplen %s", optarg);
  212.                         break;
  213.  
  214.                 case 'S':
  215.                         ++Sflag;
  216.                         break;
  217.  
  218.                 case 't':
  219.                         --tflag;
  220.                         break;
  221.  
  222.                 case 'T':
  223.                         if (strcasecmp(optarg, "vat") == 0)
  224.                                 packettype = PT_VAT;
  225.                         else if (strcasecmp(optarg, "wb") == 0)
  226.                                 packettype = PT_WB;
  227.                         else if (strcasecmp(optarg, "rpc") == 0)
  228.                                 packettype = PT_RPC;
  229.                         else if (strcasecmp(optarg, "rtp") == 0)
  230.                                 packettype = PT_RTP;
  231.                         else if (strcasecmp(optarg, "rtcp") == 0)
  232.                                 packettype = PT_RTCP;
  233.                         else
  234.                                 error("unknown packet type `%s'", optarg);
  235.                         break;
  236.  
  237.                 case 'v':
  238.                         ++vflag;
  239.                         break;
  240.  
  241.                 case 'w':
  242.                         WFileName = optarg;
  243.                         break;
  244. #ifdef YYDEBUG
  245.                 case 'Y':
  246.                         {
  247.                         /* Undocumented flag */
  248.                         extern int yydebug;
  249.                         yydebug = 1;
  250.                         }
  251.                         break;
  252. #endif
  253.                 case 'x':
  254.                         ++xflag;
  255.                         break;
  256.  
  257.                 default:
  258.                         usage();
  259.                         /* NOTREACHED */
  260.                 }
  261.  
  262.         if (tflag > 0)
  263.                 thiszone = gmt2local();
  264.  
  265.         if (RFileName != NULL) {
  266.                 /*
  267.                  * We don't need network access, so set it back to the user id.
  268.                  * Also, this prevents the user from reading anyone's
  269.                  * trace file.
  270.                  */
  271.                 setuid(getuid());
  272.  
  273.                 pd = pcap_open_offline(RFileName, ebuf);
  274.                 if (pd == NULL)
  275.                         error(ebuf);
  276.                 localnet = 0;
  277.                 netmask = 0;
  278.                 if (fflag != 0)
  279.                         error("-f and -r options are incompatible");
  280.         } else {
  281.                 if (device == NULL) {
  282.                         device = pcap_lookupdev(ebuf);
  283.                         if (device == NULL)
  284.                                 error(ebuf);
  285.                 }
  286.                 pd = pcap_open_live(device, snaplen, !pflag, 1000, ebuf);
  287.                 if (pd == NULL)
  288.                         error(ebuf);
  289.                 i = pcap_snapshot(pd);
  290.                 if (snaplen < i) {
  291.                         warning("snaplen raised from %d to %d", snaplen, i);
  292.                         snaplen = i;
  293.                 }
  294.                 if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0)
  295.                         error(ebuf);
  296.                 /*
  297.                  * Let user own process after socket has been opened.
  298.                  */
  299.                 setuid(getuid());
  300.         }
  301.         if (infile)
  302.                 cmdbuf = read_infile(infile);
  303.         else
  304.                 cmdbuf = copy_argv(&argv[optind]);
  305.  
  306.         if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
  307.                 error(pcap_geterr(pd));
  308.         if (dflag) {
  309.                 bpf_dump(&fcode, dflag);
  310.                 exit(0);
  311.         }
  312.         init_addrtoname(fflag, localnet, netmask);
  313.  
  314.         (void)signal(SIGTERM, cleanup);
  315.         (void)signal(SIGINT, cleanup);
  316.         (void)signal(SIGHUP, cleanup);
  317.  
  318.         if (pcap_setfilter(pd, &fcode) < 0)
  319.                 error(pcap_geterr(pd));
  320.         if (WFileName) {
  321.                 pcap_dumper_t *p = pcap_dump_open(pd, WFileName);
  322.                 if (p == NULL)
  323.                         error(pcap_geterr(pd));
  324.                 printer = pcap_dump;
  325.                 pcap_userdata = (u_char *)p;
  326.         } else {
  327.                 printer = lookup_printer(pcap_datalink(pd));
  328.                 pcap_userdata = 0;
  329.         }
  330.         if (RFileName == NULL) {
  331.                 (void)fprintf(stderr, "%s: listening on %s\n",
  332.                     program_name, device);
  333.                 (void)fflush(stderr);
  334.         }
  335.         if (pcap_loop(pd, cnt, printer, pcap_userdata) < 0) {
  336.                 (void)fprintf(stderr, "%s: pcap_loop: %s\n",
  337.                     program_name, pcap_geterr(pd));
  338.                 exit(1);
  339.         }
  340.         pcap_close(pd);
  341.         exit(0);
  342. }
  343.  
  344. /* make a clean exit on interrupts */
  345. RETSIGTYPE
  346. cleanup(int signo)
  347. {
  348.         struct pcap_stat stat;
  349.  
  350.         /* Can't print the summary if reading from a savefile */
  351.         if (pd != NULL && pcap_file(pd) == NULL) {
  352.                 (void)fflush(stdout);
  353.                 putc('\n', stderr);
  354.                 if (pcap_stats(pd, &stat) < 0)
  355.                         (void)fprintf(stderr, "pcap_stats: %s\n",
  356.                             pcap_geterr(pd));
  357.                 else {
  358.                         (void)fprintf(stderr, "%d packets received by filter\n",
  359.                             stat.ps_recv);
  360.                         (void)fprintf(stderr, "%d packets dropped by kernel\n",
  361.                             stat.ps_drop);
  362.                 }
  363.         }
  364.         pcap_close(pd);
  365.         exit(0);
  366. }
  367.  
  368. /* Like default_print() but data need not be aligned */
  369. void
  370. default_print_unaligned(register const u_char *cp, register u_int length)
  371. {
  372.         register u_int i, s;
  373.         register int nshorts;
  374.  
  375.         nshorts = (u_int) length / sizeof(u_short);
  376.         i = 0;
  377.         while (--nshorts >= 0) {
  378.                 if ((i++ % 8) == 0)
  379.                         (void)printf("\n\t\t\t");
  380.                 s = *cp++;
  381.                 (void)printf(" %02x%02x", s, *cp++);
  382.         }
  383.         if (length & 1) {
  384.                 if ((i % 8) == 0)
  385.                         (void)printf("\n\t\t\t");
  386.                 (void)printf(" %02x", *cp);
  387.         }
  388. }
  389.  
  390. void
  391. default_print(register const u_char *bp, register u_int length)
  392. {
  393.         register const u_short *sp;
  394.         register u_int i;
  395.         register int nshorts;
  396.  
  397.         if ((long)bp & 1) {
  398.                 default_print_unaligned(bp, length);
  399.                 return;
  400.         }
  401.         sp = (u_short *)bp;
  402.         nshorts = (u_int) length / sizeof(u_short);
  403.         i = 0;
  404.         while (--nshorts >= 0) {
  405.                 if ((i++ % 8) == 0)
  406.                         (void)printf("\n\t\t\t");
  407.                 (void)printf(" %04x", ntohs(*sp++));
  408.         }
  409.         if (length & 1) {
  410.                 if ((i % 8) == 0)
  411.                         (void)printf("\n\t\t\t");
  412.                 (void)printf(" %02x", *(u_char *)sp);
  413.         }
  414. }
  415.  
  416. __dead void
  417. usage()
  418. {
  419.         extern char version[];
  420.  
  421.         (void)fprintf(stderr, "Version %s\n", version);
  422.         (void)fprintf(stderr,
  423. "Usage: tcpdump [-deflnNOpqStvx] [-c count] [ -F file ]\n");
  424.         (void)fprintf(stderr,
  425. "\t\t[ -i interface ] [ -r file ] [ -s snaplen ]\n");
  426.         (void)fprintf(stderr,
  427. "\t\t[ -T type ] [ -w file ] [ expression ]\n");
  428.         exit(-1);
  429. }
  430.